﻿using System.Collections;
using System.Collections.Generic;
using System;


public class NetMessageDispacher 
{
    public NetMessageDispacher()
    {

    }

    public Dictionary<string, Func<NetMessageHandler>> netHandlerDict = new Dictionary<string, Func<NetMessageHandler>>();
    public void RegisterHandler(string key, Func<NetMessageHandler> netEvent )
    {
        if(netHandlerDict == null)
            netHandlerDict = new Dictionary<string, Func<NetMessageHandler>>();

        if (netHandlerDict.ContainsKey(key))
        {
            GameDebug.LogError("RegisterEvent ContainsKey: " + key);
            return;
        }
        netHandlerDict[key] = netEvent;
    }

    public void OnReceive(Remote client,MessagePacket messageReceive)
    {
//#if DEBUG
//        if (messageReceive != null && messageReceive.key != "NetRequest_Ping")
//            GameDebug.Log($"NetMessageDispacher OnReceive:{client?.ipEndPoint?.Address}  key:{ messageReceive.key}  type:{messageReceive.type}");
//#endif
        string key = messageReceive.key;

        if (messageReceive.type == MessagePacketType.Event)
        {
            if (messageReceive == null)
            {
                GameDebug.LogError("messageReceive == null");
                return;
            }
          
            if (string.IsNullOrEmpty(key))
            {
                GameDebug.LogError("key  null");
                return;
            }
            if (netHandlerDict.ContainsKey(key))
            {
                NetMessageHandler netHandler = netHandlerDict[key]();

                netHandler.Excuate(client, messageReceive);
            }
            else
            {
                GameDebug.LogError($"找不到处理相应 key:{key}  all :{netHandlerDict.GetDictStr()}"+"\n"+Environment.StackTrace);
            }
        }
        else if (messageReceive.type == MessagePacketType.Response)
        {
            NetSendToServer request = m_RequestCollection.GetNetRequest(messageReceive.seq);

            if (request != null)
            {
                try
                {
                    ResponseData newResponseData = request.NewResponseData();

                    if (newResponseData != null)
                        newResponseData.Read(messageReceive.data);


                    request.onResponse?.Invoke(newResponseData);

                    lock (m_ToRemove)
                    {
                        m_ToRemove.Add(request.message.seq);
                    }
                    //GameDebug.Log($"{request.message.key}  seq:{request.message.seq}  netsend:{request?.GetHashCode()}  请求得到回應");
                }
                catch (System.Exception e)
                {
                    request.onResponse?.Invoke(null);
                    GameDebug.LogException(e);
                }
            }
            else
            {
                GameDebug.LogError($"response 找不到处理相应 key:{key}  seq:{messageReceive.seq} all:{m_RequestCollection.requestDict.GetDictStr()} " + "\n" + Environment.StackTrace);
            }
        }
    }

    RequestCollection m_RequestCollection = new RequestCollection();
    public RequestCollection requestCollection
    {
        get { return m_RequestCollection; }
    }

    public void AddRequest(NetSendToServer request)
    {
        if (request.message == null)
        {
            GameDebug.LogError($"request.message == null ");
        }
        else
        {
            if (request.needResponse)
            {
                m_RequestCollection.AddRequest(request.message.seq, request);
            }
        }
    }

    List<int> m_ToRemove = new List<int>();
    public void Update()
    {
        double curTime = CommonFunctions.GetTimeStampSeconds();

        foreach (NetSendToServer request in this.m_RequestCollection.requestDict.Values)
        {
            if (curTime - request.sendTime > request.timeOutSeconds)
            {
                //超时了
                GameDebug.Log($"{request.message.key}  seq:{request.message.seq}  netsend:{request?.GetHashCode()}  请求超时");
                request.onTimeOut?.Invoke(request);

                lock (m_ToRemove)
                {
                    m_ToRemove.Add(request.message.seq);
                }
            }
        }
        lock (m_ToRemove)
        {
            if (m_ToRemove.Count > 0)
            {
                m_ToRemove.ForEach(e => this.m_RequestCollection.RemoveRequest(e));
                m_ToRemove.Clear();
            }
        }
    }



}

public class RequestCollection
{

    public Dictionary<int, NetSendToServer> requestDict = new Dictionary<int, NetSendToServer>();

    public void AddRequest(int seq, NetSendToServer netRequest)
    {
        if (requestDict.ContainsKey(seq))
        {
            GameDebug.LogError("AddRequest  ContainsKey:" + seq);
            return;
        }
        requestDict[seq] = netRequest;
    }

    public NetSendToServer GetNetRequest(int seq)
    {
        if (requestDict.ContainsKey(seq))
        {
            return requestDict[seq];
        }
        return null;
    }
    public void RemoveRequest(int seq)
    {
        requestDict.Remove(seq);
    }

}